﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Conv
{
    public class ConvNet
    {
        private const int Width=28;
        private const int Height = 28;
        Layer _inputLayer ;
        private ConvolutinalLayer firstConvLayer;
        private ConvolutinalLayer secondConvLayer;
        private SubsamplingLayer firstSubsLayer;
        private SubsamplingLayer secondSubsLayer;
        private FullConnectedLayer firstFullLayer;
        private FullConnectedLayer secondFullLayer;
        private ITeacheble[] _layers;

        public ConvNet()
        {
            _inputLayer = new Layer(Width, Height);
            firstConvLayer = new ConvolutinalLayer(new List<Layer>(1) { _inputLayer }, 6, 5);
            firstSubsLayer = new SubsamplingLayer(firstConvLayer.MapList,2);
            secondConvLayer = new ConvolutinalLayer(firstSubsLayer.MapList, 50, 5);
            secondSubsLayer = new SubsamplingLayer(secondConvLayer.MapList, 2);
            firstFullLayer = new FullConnectedLayer(secondSubsLayer.MapList, 100);
            secondFullLayer = new FullConnectedLayer(new List<Layer>(1){firstFullLayer}, 10);
            _layers = new ITeacheble[6];
            _layers[0] = firstConvLayer;
            _layers[1] = firstSubsLayer;
            _layers[2] = secondConvLayer;
            _layers[3] = secondSubsLayer;
            _layers[4] = firstFullLayer;
            _layers[5] = secondFullLayer;

        }
        public int  Process(double[,] inputArray)
        {
            _inputLayer.SetState(inputArray);
            for (int i = 0; i < _layers.Length; i++)
                _layers[i].Process();
            int number = 0;
            double max = -1;    
            for (int i = 0; i < secondFullLayer.Neurons.Length; i++)
            {
                if (secondFullLayer.Neurons[i, 0].State>max)
                {
                    max = secondFullLayer.Neurons[i, 0].State;
                    number = i;
                }
            }
            return number;
        }
        public void Teach(int correct)
        {

            #region Deal With Out Layer

            for (int k = 0; k < 10; k++)
            {
                Neuron currentNeuron = secondFullLayer.Neurons[k, 0];
                if (k == correct)
                {
                    //old 
                    /*currentNeuron.Sigma = (1.0 - currentNeuron.State)*
                                          currentNeuron.ActivationFuncDerivative(currentNeuron.SumInput);*/
                    currentNeuron.Sigma = (1.0 - currentNeuron.State);//currentNeuron.Sigma = (1.0 - currentNeuron.State)
                }
                else
                {
                    //old
                    /*
                    currentNeuron.Sigma = (-1.0 - currentNeuron.State)*
                                          currentNeuron.ActivationFuncDerivative(currentNeuron.SumInput);*/
                    currentNeuron.Sigma = (-1.0 - currentNeuron.State);//currentNeuron.Sigma = (-1.0 - currentNeuron.State);
                }
            }
            #endregion

            for (int i = _layers.Length - 1; i >= 0; i--)
                _layers[i].BackPropogate();

            for (int i = _layers.Length - 1; i >= 0; i--)
                _layers[i].UpdateWeight();
        }
    }
}